from copy import deepcopy

from django.http import JsonResponse

from apps.base.models import User, Rights
from django.conf import settings
from service import ret
from service.encrypt import md5
from service.per_verify import init_permission
from .forms import LoginForm
from django.views.decorators.http import require_GET
from django.views.decorators.http import require_POST
from service import res_json_data


# /login/
@require_POST
def login(request):
    form = LoginForm(request.POST)
    if not form.is_valid():
        return res_json_data.no_valid_api(form)
    mobile = form.cleaned_data['mobile']
    password = form.cleaned_data['password']
    u_obj = User.objects.filter(mobile=mobile, password_hash=md5(password)).first()
    if not u_obj:
        return res_json_data.summary_error_api(msg="用户名或密码错误!")
    if u_obj.is_deleted:
        return res_json_data.summary_error_api(msg="该用户已被注销!")
    if not u_obj.is_enabled:
        return res_json_data.summary_error_api(msg="该用户已被禁用!")
    request.session[settings.LOGIN_SESSION_KEY] = u_obj.id  # ★ 用session来实现登陆会话的保持
    init_permission(u_obj, request)  # ★ 当前用户所拥有的权限放到Django的session表中
    return JsonResponse({
        "code": ret.SUCCESS,
        'msg': "登陆成功!",
        'data': {'user_info': u_obj.json()}
    })


# /logout/
@require_GET
def logout(request):
    request.session.flush()  # 清除session,客户端和服务端的都清空
    return JsonResponse({
        "code": ret.SUCCESS,
        'msg': "注销成功!",
    })


# /menu/
@require_GET
def get_menu(request):
    """使用数据库的数据,构建一个和menu.json一样的菜单数据结构并返回回去"""
    # 1.1 获取当前用户所拥有的所有权限,筛选出可作菜单的权限 (即权限类型是auth的除外)
    # 1.2 获取当前用户所拥有的所有权限,筛选出不是目录的权限 (即权限类型是menu的除外) + 同步更新用户的权限session!!!
    current_user = request.user
    rights_obj_list = set()  # 一个用户可拥有多个角色,角色拥有的权限可能重复,所以用集合来去重
    permission_obj_list = set()
    for role_obj in current_user.role_list.filter(is_deleted=False, is_enabled=True):
        for rights_obj in role_obj.rights_list.filter(is_deleted=False, is_enabled=True):
            if rights_obj.kind != "auth":
                rights_obj_list.add(rights_obj)
            if rights_obj.kind != "menu":
                permission_obj_list.add(rights_obj)

    if request.user.is_super:  # 超级管理员拥有所有权限(软删除的除外), 禁用启用对其无影响
        rights_obj_list = Rights.objects.filter(is_deleted=False).exclude(kind="auth")
    rights_list = [rights_obj.menu_json() for rights_obj in rights_obj_list]
    rights_list.sort(key=lambda x: (x["pid"], x["id"]), reverse=True)

    permissions_list = []
    for item in permission_obj_list:
        permissions_list.append(item.url)
    request.session[settings.PERMISSION_SESSION_KEY] = permissions_list

    # 2. 实现n层动态菜单
    def build_children(pid):
        items = menu_dict[pid]
        for item in items:
            children = build_children(item["id"])  # 递归调用获取子项
            if children:  # 只有当存在子项时，才添加 children 属性
                item["children"] = sorted(children, key=lambda x: x["sort"])  # 排序子项
        return sorted(items, key=lambda x: x["sort"])  # 返回排序后的菜单项

    from collections import defaultdict
    menu_dict = defaultdict(list)  # 键不存在,则自动为该键创建一个空列表
    # 2.1 将每个菜单项放入以 pid 为键的字典中
    for menu_item in rights_list:
        menu_dict[menu_item["pid"]].append(menu_item)
    # 2.2 递归构建子菜单,并按照sort字段进行排序.
    # 从根节点开始构建菜单
    menu = build_children(0)

    return JsonResponse(menu, safe=False)
